/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "加速结构.h"

#include "core/vec_conversion.h"



bool f_是否碰撞(const S_Cube& a, const S_Cube& b) {
	vec3 sizeAh = a.size * 0.5f;
	vec3 sizeBh = b.size * 0.5f;

	vec3 a_min = { a.pos.x - sizeAh.x, a.pos.y - sizeAh.y, a.pos.z - sizeAh.z };
	vec3 a_max = { a.pos.x + sizeAh.x, a.pos.y + sizeAh.y, a.pos.z + sizeAh.z };

	vec3 b_min = { b.pos.x - sizeBh.x, b.pos.y - sizeBh.y, b.pos.z - sizeBh.z };
	vec3 b_max = { b.pos.x + sizeBh.x, b.pos.y + sizeBh.y, b.pos.z + sizeBh.z };

	if (a_max.x < b_min.x || a_min.x > b_max.x) return false;
	if (a_max.y < b_min.y || a_min.y > b_max.y) return false;
	if (a_max.z < b_min.z || a_min.z > b_max.z) return false;

	return true;
}

bool f_是否包含(const S_Cube& a, const S_Cube& b) {
	vec3 sizeAh = a.size * 0.5f;
	vec3 sizeBh = b.size * 0.5f;

	vec3 a_min = { a.pos.x - sizeAh.x, a.pos.y - sizeAh.y, a.pos.z - sizeAh.z };
	vec3 a_max = { a.pos.x + sizeAh.x, a.pos.y + sizeAh.y, a.pos.z + sizeAh.z };

	vec3 b_min = { b.pos.x - sizeBh.x, b.pos.y - sizeBh.y, b.pos.z - sizeBh.z };
	vec3 b_max = { b.pos.x + sizeBh.x, b.pos.y + sizeBh.y, b.pos.z + sizeBh.z };

	return (a_min.x >= b_min.x && a_max.x <= b_max.x && a_min.y >= b_min.y && a_max.y <= b_max.y && a_min.z >= b_min.z && a_max.z <= b_max.z);
}



bool f_bvh_包围坐标检测(const S_CubeArray* 包围盒, const S_Vec3Array* 坐标, S_Vec3Array* 包含坐标, int32 算法) {
	switch (算法) {
		case 0: {
			for (uint32 k = 0; k < 包围盒->count; ++k) {
				for (uint32 i = 0; i < 坐标->count; ++i) {
					if (f_basic_isBoxContained(包围盒->ptr_userData[k].pos, 包围盒->ptr_userData[k].size, 坐标->ptr_userData[i])) {
						f_core_array_push_back((S_Array*)包含坐标, (uint8*)&(坐标->ptr_userData[i]));
					}
				}
			}
			break;
		}
		default:
			break;
	}

	return true;
}

bool f_bvh_包围索引检测(const S_CubeArray* 包围盒, const S_Vec3Array* 坐标, S_UI32Array* 包含索引, int32 算法) {
	switch (算法) {
	case 0: {
		for (uint32 k = 0; k < 包围盒->count; ++k) {
			for (uint32 i = 0; i < 坐标->count; ++i) {
				if (f_basic_isBoxContained(包围盒->ptr_userData[k].pos, 包围盒->ptr_userData[k].size, 坐标->ptr_userData[i])) {
					f_core_array_push_back((S_Array*)包含索引, (uint8*)&(i));
				}
			}
			//vec3 当前包围盒顶点[8];
			//f_array_BoundingArray(当前包围盒顶点, 包围盒->ptr_userData[k]);
		}
		break;
	}
	default:
		break;
	}

	return true;
}

bool f_bvh_包围索引坐标(const S_CubeArray* 包围盒, const S_Vec3Array* 坐标, S_iVec3Array* 坐标索引) {
	f_core_array_resize((S_Array*)坐标索引, 0);
	vec3 单元大小 = f_core_array_getUnitSize((S_Array*)坐标);

	for (uint32 k = 0; k < 包围盒->count; ++k) {
		//uint32 offset = 坐标索引->count;
		std::vector<ivec3> coordIndex;
		ivec3 最小 = {INT_MAX, INT_MAX, INT_MAX};

		for (uint32 i = 0; i < 坐标->count; ++i) {
			vec3 point = 坐标->ptr_userData[i];
			if (f_basic_isBoxContained(包围盒->ptr_userData[k].pos, 包围盒->ptr_userData[k].size, point)) {
				
				ivec3 还原坐标索引 = _iVec3(point / 单元大小);
				最小 = vec_Min(还原坐标索引, 最小);
				coordIndex.push_back(还原坐标索引);
			}
		}

		uint32 num = coordIndex.size();
		for (uint32 i = 0; i < num; ++i) {
			coordIndex[i] = coordIndex[i] - 最小;
			f_core_array_push_back((S_Array*)坐标索引, (uint8*)&(coordIndex[i]));
		}
	}
	return false;
}

bool f_bvh_包围盒自检测(const S_CubeArray* 包围盒, const S_Cube& 坐标, int32 算法) {
	for (uint32 k = 0; k < 包围盒->count; ++k) {
		if (f_是否碰撞(包围盒->ptr_userData[k], 坐标) || f_是否包含(包围盒->ptr_userData[k], 坐标)) {
			return true;
		}
	}
	return false;
}



ivec3 f_bound_体素分辨率(const S_Cube& 包围盒, vec3 单元大小) {
	单元大小.x = 单元大小.x > 0 ? 单元大小.x : 0.0000001;
	单元大小.y = 单元大小.y > 0 ? 单元大小.y : 0.0000001;
	单元大小.z = 单元大小.z > 0 ? 单元大小.z : 0.0000001;

	ivec3 分辨率 = _iVec3(包围盒.size / 单元大小);
	return 分辨率;
}

void f_bounds_体素分辨率(const S_CubeArray* 包围盒, const S_Vec3Array* 单元大小, S_iVec3Array* 分辨率) {
	uint32 num = DEF_Max(包围盒->count, 单元大小->count);
	bool 包围盒多例 = 包围盒->count >= num;
	bool 单元大小多例 = 单元大小->count >= num;

	f_core_array_resize((S_Array*)分辨率, num);

	for (uint32 i = 0; i < num; ++i) {
		ivec3 a = f_bound_体素分辨率(包围盒多例 ? 包围盒->ptr_userData[i] : 包围盒->ptr_userData[0]
						, 单元大小多例 ? 单元大小->ptr_userData[i] : 单元大小->ptr_userData[0]);

		分辨率->ptr_userData[i] = a;
	}
}







